-
Notifications
You must be signed in to change notification settings - Fork 86
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(TransactionFeedV2): Add initial implementation of Transaction Feed V2 #6135
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## slava/add-rtk-query #6135 +/- ##
=====================================================
Coverage 88.75% 88.76%
=====================================================
Files 731 733 +2
Lines 30827 30972 +145
Branches 5630 5358 -272
=====================================================
+ Hits 27362 27493 +131
- Misses 3266 3434 +168
+ Partials 199 45 -154
... and 66 files with indirect coverage changes Continue to review full report in Codecov by Sentry.
|
// eslint-disable-next-line react-hooks/rules-of-hooks | ||
pageData: useMemo( | ||
() => ({ | ||
currentCursor: result.originalArgs?.endCursor, // timestamp from the last transaction from the previous page. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These will be changed to use pageInfo
data from the blockchain-api response once the pagination-related PR is merged.
return { | ||
...result, | ||
// eslint-disable-next-line react-hooks/rules-of-hooks | ||
pageData: useMemo( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added a comment explaining the usage of this useMemo
and some other parts in the next PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok but this is a bit disturbing to me for now 😅
It's not yet clear to me that it's always called.
And not messing something up with what React expects for hooks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome! 🎉
Approved with some suggestions / questions.
} | ||
|
||
// Query poll interval | ||
const POLL_INTERVAL = 10000 // 10 secs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:
const POLL_INTERVAL = 10000 // 10 secs | |
const POLL_INTERVAL_MS = 10_000 // 10 secs |
return { | ||
...result, | ||
// eslint-disable-next-line react-hooks/rules-of-hooks | ||
pageData: useMemo( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok but this is a bit disturbing to me for now 😅
It's not yet clear to me that it's always called.
And not messing something up with what React expects for hooks.
} | ||
|
||
function renderItem({ item: tx }: { item: TokenTransaction; index: number }) { | ||
switch (tx.__typename) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we use tx.type
instead?
__typename
is something added by GraphQL and I wanted to avoid relying on it with the new implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jeanregisser this will introduce a small drop in type-safety and will require some extra type casting. Shouldn't be a problem for now but potentially something that we might want to revisit once we move to TransactionFeedV2 completely.
{ skip: !address, pollingInterval: POLL_INTERVAL } | ||
) | ||
|
||
useEffect(() => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: related to https://valora-app.slack.com/archives/C025V1D6F3J/p1728479551405369
useEffect(() => { | |
useEffect(function updatePaginatedData() { |
import { walletAddressSelector } from 'src/web3/selectors' | ||
|
||
type PaginatedData = { | ||
[timestamp: number]: TokenTransaction[] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we type it like this? In case we read it with a timestamp that wasn't added?
[timestamp: number]: TokenTransaction[] | |
[timestamp: number]: TokenTransaction[] | undefined |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jeanregisser I still plan to introduce the data persistence (with some workarounds) to have that instant first page load as we have on the existing transaction feed. But I agree - this should include undefined
while the persistence is absent.
Or alternatively, instead of this:
const [paginatedData, setPaginatedData] = useState<PaginatedData>({})
I can define it like this:
const [paginatedData, setPaginatedData] = useState<PaginatedData>({ [FIRST_PAGE_TIMESTAMP]: [] })
The first page will always be refreshed anyways so it can be empty from the start.
}) | ||
}) | ||
|
||
describe('TransactionFeed', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
describe('TransactionFeed', () => { | |
describe('TransactionFeedV2', () => { |
expect(tree.getByText('feedItemFailedTransaction')).toBeTruthy() | ||
}) | ||
|
||
it('tries to fetch 20 transactions, unless the end is reached', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this should be the name of the new test?
And there would be another one checking it fetches the first page initially?
it('tries to fetch 20 transactions, unless the end is reached', async () => { | |
it('fetches the next page by scrolling to the end of the list', async () => { |
I don't think we need the previous behavior of automatically loading the next page
that we added in #2779 which is why this name for the test was used.
Right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-
Sorry for the confusion! I've already renamed this and the next test in the next PR
-
I've also already added similar test in the next PR
-
There's no behaviour for fetching next pages if the current one is absent. Probably me keeping most of the old tests' names is the reason for the confusion. I'll revisit all the test names in the follow-up PR!
it('tries to fetch 10 transactions, and stores empty pages', async () => { | ||
mockFetch | ||
.mockResponseOnce(typedResponse({ transactions: [mockTransaction()] })) | ||
.mockResponseOnce(typedResponse({ transactions: [] })) | ||
|
||
const { store, ...tree } = renderScreen() | ||
|
||
await store.dispatch( | ||
transactionFeedV2Api.endpoints.transactionFeedV2.initiate({ address: '0x00', endCursor: 0 }) | ||
) | ||
await store.dispatch( | ||
transactionFeedV2Api.endpoints.transactionFeedV2.initiate({ address: '0x00', endCursor: 123 }) | ||
) | ||
|
||
await waitFor(() => tree.getByTestId('TransactionList')) | ||
|
||
await waitFor(() => expect(mockFetch).toHaveBeenCalledTimes(2)) | ||
expect(getNumTransactionItems(tree.getByTestId('TransactionList'))).toBe(1) | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need this one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jeanregisser I think you're right that we can skip this. In the next PR I've added a test that checks for correct lazy-load of a few pages of data so that should cover the same thing this test was covering.
useTransactionFeedV2Query( | ||
{ address: address!, endCursor: FIRST_PAGE_TIMESTAMP }, | ||
{ skip: !address, pollingInterval: POLL_INTERVAL } | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand correctly, this will cause the other hook to return new data?
That's why we're not reading the result from it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jeanregisser Correct. Multiple usages of the same hook with the same arguments will retrieve the data from single cached data point within the api reducer that library manages itself.
So we can even call this hook in multiple places to retrieve data and if at any moment that data updates anywhere – all the usages will instantly get updated with the new data.
The same goes for this polling example. It's task is only to trigger the fetch every 10 sec and once the data is updated - the hook above with the selectFromResult
will trigger all the necessary changes and re-renders.
@jeanregisser Updated as per the comments! Also, found a bug in logic of updating the pagination data for the first page so I've updated that as well. |
### Description 3rd PR for RET-1207. It merges existing confirmed (failed/completed) transaction from the `standByTransactions` reducer into each paginated data. ### Test plan WIP ### Related issues - Relates to RET-1207 ### Backwards compatibility Yes ### Network scalability If a new NetworkId and/or Network are added in the future, the changes in this PR will: - [x] Continue to work without code changes, OR trigger a compilation error (guaranteeing we find it when a new network is added)
Description
2nd PR for RET-1207. Implements the following list of basic Transactions Feed functionality:
pendingStandByTransactionsSelector
More comments for different parts of the pagination flow are added as comments in the file in the next PR.
Test plan
10 out of 16 tests from
TransactionFeed.test.ts
were re-used and adjusted to the new data fetching flow. Other tests will be added in the follow-up PRs purely for the sake of trying to keep the PRs smaller.Related issues
Backwards compatibility
Yes
Network scalability
If a new NetworkId and/or Network are added in the future, the changes in this PR will: